package com.ruoyi.basedata.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.CastUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.basedata.domain.Concentrator;
import com.ruoyi.basedata.domain.ConcentratorCommandLogs;
import com.ruoyi.basedata.domain.RedisKeyName;
import com.ruoyi.basedata.domain.TerminalsXb;
import com.ruoyi.basedata.domain.vo.ConcentratorCommand;
import com.ruoyi.basedata.domain.vo.ConcentratorProtocol;
import com.ruoyi.basedata.mapper.ConcentratorCommandLogsMapper;
import com.ruoyi.basedata.mapper.ConcentratorMapper;
import com.ruoyi.basedata.mapper.MeterSheetsMapper;
import com.ruoyi.basedata.mapper.TerminalsXbMapper;
import com.ruoyi.basedata.service.IConcentratorService;
import com.ruoyi.basedata.service.ITerminalsXbService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.*;
import com.ruoyi.system.mapper.SysSheetUsersMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 集中器管理Service业务层处理
 *
 * @author ruoyi
 * @date 2023-12-18
 */
@Service
@Slf4j
public class ConcentratorServiceImpl implements IConcentratorService {

    @Resource
    private Environment env;

    private static final String concentrator_key = "concentratorDetail";

    private static final Map<Integer, String> sendMap = new HashMap<Integer, String>() {{
        put(4, "getCommandDataForValveControl"); // 阀控
        put(1, "getCommandDataForMeterReadingAll");// 抄表
        put(2, "getCommandDataForBoundMeter");
    }};
    private static final Map<Integer, String> resultMap = new HashMap<Integer, String>() {{
        put(2, "getValveControlReslut");
    }};
    @Autowired
    private ConcentratorMapper concentratorMapper;

    @Autowired
    private TerminalsXbMapper terminalsXbMapper;

    @Autowired
    private ConcentratorCommandLogsMapper commandLogsMapper;
    @Autowired
    private MeterSheetsMapper meterSheetsMapper;
    @Autowired
    private RedisCache redisCache;

    @Override
    public JSONObject sendCommand(ConcentratorCommand concentratorCommand) {
        String aClassName = getClassName(concentratorCommand);
        System.out.println(concentratorCommand);
        JSONObject jsonObject = new JSONObject();
        String requestUrl;
        String responseUrl;
        String communicationType = concentratorCommand.getCommunicationType();
        try {
            String communicationTypeUrl = DictUtils.getDictLabel("communication_type", concentratorCommand.getCommunicationType());
            requestUrl = env.getProperty("netty-url." + communicationTypeUrl + "." + "requestNetty");
            responseUrl = env.getProperty("netty-url." + communicationTypeUrl + "." + "responseNetty");
        } catch (NullPointerException nullPointerException) {
            jsonObject.put("msg", "集中器通讯类型未确定");
            jsonObject.put("code", "1");
            return jsonObject;
        }
//        String ip = env.getProperty("netty-url." + communicationType + "." + "ip");
//        String port = env.getProperty("netty-url." + communicationType + "." + "port");
        // 获取命令
        byte[] command;
        switch (concentratorCommand.getCommandType()) {
            case 1:
                // 抄表
                try {
                    command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForMeterReadingAll", new Object[]{concentratorCommand.getConcentratorId()});
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 300L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 2:
                // 配绑定置多个水表地址
                List<TerminalsXb> terminalsXbs = concentratorCommand.getTerminalsXbs();
                List<TerminalsXb> meters = terminalsXbs.stream().sorted(Comparator.comparing(TerminalsXb::getId)).collect(Collectors.toList());
                List<List<TerminalsXb>> meterLists = CollectionUtils.subListByCount(meters, 20);
//                List<JSONObject> list = new ArrayList<>();
//                Map<String,Object> map = new HashMap<>();
                for (List<TerminalsXb> meterList : meterLists) {
                    try {
                        Thread.sleep(3000);
                        String[] metersArray = meterList.stream().map(TerminalsXb::getCommunicateAddress).toArray(String[]::new);
                        String[] collectArray = meterList.stream().map(TerminalsXb::getCollectorAddress).toArray(String[]::new);
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForBoundMeter", new Object[]{metersArray, collectArray, concentratorCommand.getConcentratorId()});
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmssSSS");
                        System.out.println(sdf.format(new Date()));
                        log.info(Arrays.toString(metersArray) + "开始下发绑定命令");
                        log.info("数据包" + Arrays.toString(command));
                        CommonHelper.getNettyBackBody(concentratorCommand.getConcentratorId(), command, requestUrl, communicationType);
                        jsonObject.put("msg", "命令下发成功");
                    } catch (Exception e) {
                        log.info(e.getMessage());
                        jsonObject.put("msg", "命令下发失败");
                    }
                    createCommandLog(JSON.toJSONString(meterList.stream().map(TerminalsXb::getTerminalId).collect(Collectors.toList())),
                            concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                }
                jsonObject.put("msg", "命令下发成功");
                jsonObject.put("code", 0);
                break;
            case 3:
                // 单独抄一个表数据
                try {
                    command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForMeterReadingOne", new Object[]{concentratorCommand.getConcentratorId(), concentratorCommand.getMeter()});
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 4:
                // 开关阀控制
                String operation = "1".equals(concentratorCommand.getIsOpen()) ? "开阀" : "关阀";
                try {
                    command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForValveControl", new Object[]{concentratorCommand.getConcentratorId(), concentratorCommand.getMeter(), concentratorCommand.getIsOpen()});
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);

                    jsonObject.put("msg", operation + jsonObject.getString("msg"));
                } catch (Exception e) {
                    log.error("系统异常，" + operation + "命令下发失败", e);
                    jsonObject.put("msg", "系统异常，" + operation + "命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 5:
                // 设置自动抄表上报时间及周期
                try {
                    command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForFrequencyControl", new Object[]{concentratorCommand});
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.error("系统异常，命令下发失败", e);
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 6:
                // 设置ip和端口
                try {
                    command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForIpPortControl", new Object[]{concentratorCommand.getIp(), concentratorCommand.getPort(), concentratorCommand.getConcentratorId()});
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 7:
                // 批量读取缓存的最新抄表数据
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForMeterReadingAllNew", new Object[]{});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 8:
                // 查询集中器地址
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForConcentratorAddress", new Object[]{concentratorCommand.getConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 9:
                // 查询集中器抄表日
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForConcentratorReadingDay", new Object[]{concentratorCommand.getConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 10:
                // 查询计量表运行参数(读取表地址)
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForMeterAddress", new Object[]{concentratorCommand.getConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 800L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 11:
                // 查询集中器时钟
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForConcentratorDate", new Object[]{concentratorCommand.getConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.error("系统异常，命令下发失败", e);
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 12:
                // 查询集中器的ip和端口
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForConcentratorIpPort", new Object[]{concentratorCommand.getConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 13:
                // 设置集中器地址
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForSetConcentratorAddress", new Object[]{concentratorCommand.getConcentratorId(), concentratorCommand.getNewConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.error("系统异常，命令下发失败", e);
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 14:
                // 下载表档案(单个)
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForDownMeterOne", new Object[]{concentratorCommand.getConcentratorId(), concentratorCommand.getMeter(), concentratorCommand.getCollector()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 15:
                // 集中器校时
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForSetConcentratorDate", new Object[]{concentratorCommand.getConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.error("系统异常，命令下发失败", e);
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 16:
                // 集中器初始化
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForConcentratorInitialize", new Object[]{concentratorCommand.getConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 17:
                // 集中器格式化
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForConcentratorFormat", new Object[]{concentratorCommand.getConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.error("系统异常，命令下发失败", e);
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 18:
                // 恢复出厂设置
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForConcentratorFactoryReset", new Object[]{concentratorCommand.getConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 19:
                // 集中器重启
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForConcentratorReboot", new Object[]{concentratorCommand.getConcentratorId()});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.info(e.getMessage());
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 20:
                // 多抄
                try {
                    command = (byte[]) CommonHelper.getMethod(aClassName, "getCommandDataForMultiCopy", new Object[]{concentratorCommand});
                } catch (Exception e) {
                    // 捕获被调用方法的实际异常
                    Throwable cause = e.getCause();
                    if (cause instanceof IllegalArgumentException) {
                        log.error("多抄失败", e);
                        jsonObject.put("msg", e.getMessage());
                        jsonObject.put("code", "1");
                    } else if (cause instanceof NullPointerException) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                    } else {
                        log.error("系统异常，命令下发失败", e);
                        jsonObject.put("msg", "系统异常，命令下发失败");
                        jsonObject.put("code", "1");
                    }
                    break;
                }
                jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 21:
                // 千宝通下载档案
                try {
                    if (org.apache.commons.collections4.CollectionUtils.isEmpty(concentratorCommand.getTerminalsXbs())) {
                        TerminalsXb condition = new TerminalsXb();
                        condition.setConcentratorAddress(concentratorCommand.getConcentratorId());
                        condition.setTerminalMark(1);
                        concentratorCommand.setTerminalsXbs(terminalsXbMapper.selectTerminalsXbList(condition));
                    }
                    List<TerminalsXb> nullMeterSeq = concentratorCommand.getTerminalsXbs().stream().filter(e -> e.getMeterSeq() == null).collect(Collectors.toList());
                    if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(nullMeterSeq)) {
                        List<String> meterNumbers = nullMeterSeq.stream().map(TerminalsXb::getTerminalId).collect(Collectors.toList());
                        jsonObject.put("msg", String.format("表%s序号不存在，命令下发失败", meterNumbers));
                        jsonObject.put("code", "1");
                        break;
                    }
                    String meterNumbers = StringUtils.join(concentratorCommand.getTerminalsXbs().stream().map(TerminalsXb::getTerminalId).collect(Collectors.toList()), ",");
                    concentratorCommand.setMeter(meterNumbers);
                    List<byte[]> commands = Convert.toList(byte[].class, CommonHelper.getMethod(aClassName, "getCommandDataForDownloadProfile", new Object[]{concentratorCommand}));
                    for (byte[] cmd : commands) {
                        jsonObject = sendResult(cmd, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                        Thread.sleep(10000);
                    }

                } catch (Exception e) {
                    log.error("系统异常，命令下发失败", e);
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            case 22:
                // 启停自动上报
                try {
                    try {
                        command = (byte[]) CommonHelper.getMethod(aClassName, "getSetAutoReport", new Object[]{concentratorCommand});
                    } catch (NullPointerException e) {
                        jsonObject.put("msg", "暂未开通此命令");
                        jsonObject.put("code", "1");
                        createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                        break;
                    }
                    jsonObject = sendResult(command, aClassName, concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), 100L, requestUrl, responseUrl, communicationType);
                } catch (Exception e) {
                    log.error("系统异常，命令下发失败", e);
                    jsonObject.put("msg", "系统异常，命令下发失败");
                    jsonObject.put("code", "1");
                }
                createCommandLog(concentratorCommand.getMeter(), concentratorCommand.getConcentratorId(), concentratorCommand.getCommandType(), jsonObject);
                break;
            default:
                jsonObject.put("msg", "无法识别此命令");
                jsonObject.put("code", "1");
                break;
        }
        return jsonObject;
    }

    private JSONObject sendResult(byte[] command, String aClassName, String concentratorID, Integer concentratorType, Long waitTime, String requestUrl, String responseUrl, String communicationType) {
        JSONObject jsonObject = new JSONObject();
        JSONObject jsonObject2 = new JSONObject();
        // 下发命令
        String requestId = CommonHelper.getNettyBackBody(concentratorID, command, requestUrl, communicationType);
        System.out.println(requestId);
        if (requestId == null) {
            jsonObject.put("code", 0);
            jsonObject.put("msg", "命令下发失败");
            log.error("命令下发失败，requestId： null ");
        } else {
//            String cmdResponseBody = CommonHelper.getCmdResponseBody(concentratorID, requestId, 0, 3, ip, Integer.parseInt(port));
            ArrayList<String> cmdResponseBody = CommonHelper.getCmdResponseBody(concentratorID, requestId, 0, 3, responseUrl, waitTime);
//            if (cmdResponseBody == null || cmdResponseBody.equals("")) {
//                jsonObject.put("code", 0);
//                jsonObject.put("msg", "命令下发成功，无响应");
            if (cmdResponseBody.isEmpty()) {
                jsonObject.put("code", 0);
                jsonObject.put("msg", "命令下发成功，无响应");
            } else {
                log.info("本次命令下发返回结果" + cmdResponseBody);
                for (String s : cmdResponseBody) {
                    Object getResult = CommonHelper.getMethod(aClassName, "GetResult", new Object[]{hexStringToByteArray(s), concentratorType});
                    jsonObject2 = (JSONObject) getResult;
                    if (jsonObject2 != null && StringUtils.isNotBlank(jsonObject2.getString("data"))) {
                        if (jsonObject.getString("data") == null || Objects.equals(jsonObject.getString("data"), "")) {
                            jsonObject.put("data", jsonObject2.getString("data"));
                        } else {
                            jsonObject.put("data", jsonObject.getString("data") + jsonObject2.getString("data"));
                        }
                    }
                }
                if (jsonObject2 != null && "1".equals(jsonObject2.get("code"))) {
                    jsonObject.put("requestId", requestId);
                    jsonObject.put("msg", "命令下发成功，设备已接收");
                } else {
                    jsonObject.put("msg", "命令下发失败");
                }
                System.out.println(jsonObject.getString("data"));
            }
        }
        return jsonObject;
    }

    @Override
    public JSONObject getCommandResult(ConcentratorCommand concentratorCommand) {
        String aClassName = getClassName(concentratorCommand);
        String responseBody = CommonHelper.getCmdResponseBody(concentratorCommand.getConcentratorId(), concentratorCommand.getRequestId(), 0, 3, "47.96.127.70", 8099);
        if (responseBody != null && !responseBody.equals("")) {
            Object getBufferPacketForAll = CommonHelper.getMethod(aClassName, "GetBufferPacketForAll", new Object[]{hexStringToByteArray(responseBody)});
            return (JSONObject) getBufferPacketForAll;
        } else {
            return null;
        }
    }

    /**
     * 导入集中器
     *
     * @param list 集中器list
     */
    @Override
    public void importData(List<Concentrator> list) {
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(list)) {
            throw new ServiceException("没有可导入的数据");
        } else {
            StringBuilder errorMsg = new StringBuilder();
            List<String> allSheetsCode = meterSheetsMapper.selectAllSheetsCode();
            List<String> allConcentratorName = concentratorMapper.selectAllConcentratorName();
            List<String> allConcentratorAddress = concentratorMapper.selectAllConcentratorAddress();
            Map<String, Integer> concentratorNameMap = new HashMap<>(list.size());
            Map<String, Integer> concentratorAddressMap = new HashMap<>(list.size());
            for (int i = 0; i < list.size(); i++) {
                Concentrator concentrator = list.get(i);
                String sheetsCode = concentrator.getSheetsCode();
                String concentratorName = concentrator.getConcentratorName();
                String concentratorAddress = concentrator.getConcentratorId();
                String tenantId = concentrator.getTenantId();
                String protocolId = concentrator.getProtocolId();
                String supplierId = concentrator.getSupplierId();
                if (StringUtils.isAnyBlank(sheetsCode, concentratorName, concentratorAddress, tenantId, protocolId, supplierId)) {
                    errorMsg.append("第").append(i + 2).append("行数据错误，区域编码、集中器名称、集中器地址、客户编号、协议类型、厂家编码均不能为空\n");
                }
                if (!allSheetsCode.contains(sheetsCode)) {
                    errorMsg.append("第").append(i + 2).append("行数据错误，区域编号不存在\n");
                }
                if (allConcentratorName.contains(concentratorName)) {
                    errorMsg.append("第").append(i + 2).append("行数据错误，集中器名称已存在\n");
                }
                if (concentratorNameMap.get(concentratorName) != null) {
                    errorMsg.append("第").append(i + 2).append("行数据错误，").append("集中器名称和第").append(concentratorNameMap.get(concentratorName) + 2).append("行集中器名称重复\n");
                } else {
                    concentratorNameMap.put(concentratorName, i);
                }
                if (allConcentratorAddress.contains(concentratorAddress)) {
                    errorMsg.append("第").append(i + 2).append("行数据错误，集中器地址已存在\n");
                }
                if (concentratorAddressMap.get(concentratorAddress) != null) {
                    errorMsg.append("第").append(i + 2).append("行数据错误，").append("集中器地址和第").append(concentratorAddressMap.get(concentratorAddress) + 2).append("行集中器地址重复\n");
                } else {
                    concentratorAddressMap.put(concentratorAddress, i);
                }
            }
            if (errorMsg.length() == 0) {
                concentratorMapper.insertConcentratorBatch(list);
                // 2024-10-25 批量导入时，存入redis
                for (Concentrator c : list) {
                    ConcentratorProtocol concentratorProtocol = concentratorMapper.selectConcentratorProtocolList(c).get(0);// 需要存储classname等
                    redisCache.setCacheMapValue(RedisKeyName.concentratorInfor + c.getSupplierId(), c.getConcentratorId(), concentratorProtocol);
                }

            } else {
                throw new ServiceException(errorMsg.toString());
            }
        }
    }

    @Override
    public boolean bindTerminalsXb(Long concentratorId, String protocolId, List<Long> terminalIds) {
        if (ObjectUtils.anyNull(concentratorId, protocolId, terminalIds)) {
            throw new IllegalArgumentException("参数不能为null");
        } else if (protocolId.isEmpty() || terminalIds.isEmpty()) {
            throw new IllegalArgumentException("协议和待绑定表id不能为空");
        }
        // // 找出绑定过其他集中器的户表设备编号
        // LambdaQueryWrapper<TerminalsXb> boundTerminalWrapper = Wrappers.lambdaQuery();
        // boundTerminalWrapper.select(TerminalsXb::getTerminalId).ne(TerminalsXb::getConcentratorId, concentratorId).in(TerminalsXb::getId, terminalIds).isNotNull(TerminalsXb::getConcentratorId);
        // // 绑定过其他集中器的户表设备编号
        // List<Object> boundTerminals = terminalsXbMapper.selectObjs(boundTerminalWrapper);
        // if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(boundTerminals)) {
        //     throw new ServiceException(String.format("表编号为%s的表已经绑定过其他集中器，请取消绑定后再绑定该集中器", boundTerminals));
        // }
        Integer maxSeq = null;
        if (Objects.equals(protocolId, ITerminalsXbService.QIANBAOTONG_PROTOCOL_ID)) {
            // 千宝通协议重新编号
            // 千宝通协议需要额外增加表序号
            maxSeq = terminalsXbMapper.selectMaxMeterSeq(ITerminalsXbService.QIANBAOTONG_PROTOCOL_ID, concentratorId);
        }
        for (Long id : terminalIds) {
            TerminalsXb xb = new TerminalsXb();
            xb.setId(id);
            xb.setConcentratorId(concentratorId);
            if (maxSeq != null) {
                int meterSeq = maxSeq + 1;
                maxSeq++;
                xb.setMeterSeq(meterSeq);
                xb.setCommunicateAddress(concentratorId + "-" + meterSeq);
            }
            terminalsXbMapper.updateTerminalsXb(xb);
        }
        return true;
    }

    private void createCommandLog(String terminalIds, String ConcentratorID, Integer commandType, JSONObject jsonObject) {
        Concentrator concentrator = new Concentrator();
        concentrator.setConcentratorId(ConcentratorID);
        List<ConcentratorProtocol> concentratorProtocols = concentratorMapper.selectConcentratorProtocolList(concentrator);
        ConcentratorCommandLogs commandLogs = ConcentratorCommandLogs.builder().tenantId(concentratorProtocols.get(0).getTenantId()).concentratorId(ConcentratorID).commandType(commandType)
                .sendTime(new Date()).feedback(jsonObject.getString("msg")).terminalIds(terminalIds)
                .build();
        if (jsonObject.getString("data") != null && jsonObject.getString("data") != "") {
            commandLogs.setInformation(jsonObject.getString("data"));
        }
        commandLogsMapper.insertConcentratorCommandLogs(commandLogs);
    }

    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }

    /**
     * 查询集中器管理
     *
     * @param ID 集中器管理主键
     * @return 集中器管理
     */
    @Override
    public Concentrator selectConcentratorByID(Long ID) {
        return concentratorMapper.selectConcentratorByID(ID);
    }

    /**
     * 查询集中器管理列表
     *
     * @param concentrator 集中器管理
     * @return 集中器管理
     */
    @Override
    public List<Concentrator> selectConcentratorList(Concentrator concentrator) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        Integer systemFlag = user.getSystemFlag();
        if (!Objects.equals(systemFlag, Constants.SYS_FLAG_ADMIN)) {
            concentrator.getParams().put("sysUserId", user.getUserId());
            if (Objects.equals(systemFlag, Constants.SYS_FLAG_NORMAL_USER)) {
                concentrator.setTenantId(user.getTenantId());
            }
        }
        return concentratorMapper.selectConcentratorList(concentrator);
    }

    /**
     * 根据通讯地址、厂家编码查询设备
     *
     * @param concentrator
     * @return
     */
    @Override
    public List<ConcentratorProtocol> selectConcentratorProtocolList(Concentrator concentrator) {
        return concentratorMapper.selectConcentratorProtocolList(concentrator);
    }

    /**
     * 新增集中器管理
     *
     * @param concentrator 集中器管理
     * @return 结果
     */
    @Override
    public int insertConcentrator(Concentrator concentrator) {
        System.out.println(JSONUtil.toJsonStr(concentrator));
        Long count = concentratorMapper.selectCount(new LambdaQueryWrapper<Concentrator>()
                .eq(Concentrator::getSupplierId, concentrator.getSupplierId())
                .eq(Concentrator::getConcentratorId, concentrator.getConcentratorId()));
        if (count > 0) {
            return 0;
        }
        int flag = concentratorMapper.insertConcentrator(concentrator);
        if (flag > 0) {
            ConcentratorProtocol concentratorProtocol = concentratorMapper.selectConcentratorProtocolList(concentrator).get(0);// 需要存储classname等
            redisCache.setCacheMapValue(RedisKeyName.concentratorInfor + concentrator.getSupplierId(), concentrator.getConcentratorId(), concentratorProtocol);
        }

        return flag;
    }

    /**
     * 修改集中器管理
     *
     * @param concentrator 集中器管理
     * @return 结果
     */
    @Override
    public int updateConcentrator(Concentrator concentrator) {
        int flag = concentratorMapper.updateConcentrator(concentrator);
        if (flag > 0) {
            redisCache.setCacheMapValue(RedisKeyName.concentratorInfor + concentrator.getSupplierId(), concentrator.getConcentratorId(), concentrator);
        }
        return flag;
    }

    /**
     * 批量删除集中器管理
     *
     * @param IDs 需要删除的集中器管理主键
     * @return 结果
     */
    @Override
    public List<String> deleteConcentratorByIDs(Long[] IDs) {
        List<Concentrator> concentrators = concentratorMapper.selectBatchIds(Arrays.asList(IDs));
        List<String> failList = new ArrayList<>();
        List<Long> deleteList = new ArrayList<>();
        concentrators.forEach(concentrator -> {
            Long count = terminalsXbMapper.selectCount(new LambdaQueryWrapper<TerminalsXb>()
                    .eq(TerminalsXb::getConcentratorId, concentrator.getId()));
            if (count > 0) {
                failList.add(concentrator.getConcentratorName());
            } else {
                deleteList.add(concentrator.getId());
            }
        });
        if (deleteList.size() > 0) {
            concentratorMapper.deleteBatchIds(deleteList);
        }

        return failList;
    }

    /**
     * 删除集中器管理信息
     *
     * @param ID 集中器管理主键
     * @return 结果
     */
    @Override
    public int deleteConcentratorByID(Long ID) {
        return concentratorMapper.deleteById(ID);
    }

    private String getClassName(ConcentratorCommand concentratorCommand) {
        String aClassName = "";
        ConcentratorProtocol concentrator = new ConcentratorProtocol();
        concentrator.setConcentratorId(concentratorCommand.getConcentratorId());
        try {
            List<ConcentratorProtocol> concentratorProtocols = concentratorMapper.selectConcentratorProtocolList(concentrator);
            ConcentratorProtocol concentratorProtocol = concentratorProtocols.get(0);
            aClassName = concentratorProtocol.getClassName();
        } catch (Exception e) {
            log.info(concentrator.getConcentratorId() + "没有找到此集中器档案");
        }
        if ("".equals(aClassName) || null == aClassName) {
            aClassName = "com.ruoyi.datastatistics.Agreement.GuoXinDTUV1";
        }
        return aClassName;
    }
}
